package com.june.junemplayer.utils;

import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 如果当前正在播放则返回true，否则返回false
 * public native boolean isPlaying();
 * 设置播放器音量，参数为0.0-1.0范围内的数据
 * public void setVolume(float leftVolume,float rightVolume);
 * 将播放器设置为循环播放或非循环播放
 * public native void setLooping(boolean looping);
 * 检查MediaPlayer是循环播放还是非循环播放
 * public native boolean isLooping();
 *
 */

public class MediaPlayerUtil {

    public MediaPlayerUtil() {
    }

    private static final int HANDLER_PLAY_TIME = 1;
    //进度条状态刷新时间间隔
    private static final int TIMER_SEEK = 20;

    private MediaPlayer mMediaPlayer;

    private Handler mUiHandler;//用来更新ui
    private Handler mTimeHandler;//定时轮询，更新seekBar
    private Runnable timerRun;

    private MediaPlayStatus mStatus = MediaPlayStatus.IDLE;

    private ExecutorService mSingleExecutorService;

    private OnMediaStateListener mOnMediaStateListener;

    public void setOnMediaStateListener(OnMediaStateListener onMediaStateListener){
        mOnMediaStateListener=onMediaStateListener;
    }

    public void init() {
        mSingleExecutorService = Executors.newSingleThreadExecutor();
        initData();
        initPlay();
    }

    private void initData() {
        mUiHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                //更新当前时间
                int currentPosition = mMediaPlayer.getCurrentPosition();
                if (mOnMediaStateListener != null) {
                    mOnMediaStateListener.onCompletion();
                }
            }
        };
    }

    private void initPlay() {
        Log.i("JuneMediaPlayer", "------initPlay() start:status = " + mStatus+"------");
        mMediaPlayer = new MediaPlayer();
        mStatus = MediaPlayStatus.IDLE;

        //当流媒体播放完毕的时候回调
        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Log.i("JuneMediaPlayer", "------setOnCompletionListener.onCompletion() start:status = " + mStatus+"------");
                stopTimer();
                mStatus = MediaPlayStatus.PLAYBACK_COMPLETED;
                if (mOnMediaStateListener != null) {
                    mOnMediaStateListener.onCompletion();
                }
                Log.i("JuneMediaPlayer", "------setOnCompletionListener.onCompletion() end:status = " + mStatus+"------");
            }
        });

        /**
         * 需要注意的是，一旦发生错误，即使应用程序尚未注册错误侦听器，
         * MediaPlayer对象也会进入Error状态。
         * 为了从处于Error状态的MediaPlayer对象并从错误中恢复，
         * reset()可以调用将对象恢复到其IDLE状态
         */
        mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                Log.i("JuneMediaPlayer", "------setOnErrorListener.onError() start:status = " + mStatus+"------");
                mStatus = MediaPlayStatus.ERROR;
                if (mOnMediaStateListener != null) {
                    //在外部onError回调中调用reset()重置状态，并重置相关的UI状态
                    mOnMediaStateListener.onError();
                }
                /**
                 * 如果该方法处理了错误，则返回true，否则返回false
                 * 返回false或根本没有onErrorListener将导致调用
                 * onCompletionListener
                 */
                Log.i("JuneMediaPlayer", "------setOnErrorListener.onError() end:status = " + mStatus+"------");
                return true;
            }
        });

        //prepare完成后，才可以播放->start
        mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                Log.i("JuneMediaPlayer", "------setOnPreparedListener.onPrepared() start:status = " + mStatus+"------");
                mStatus = MediaPlayStatus.PREPARED;

                //取消转圈
                if (mOnMediaStateListener != null) {
                    mOnMediaStateListener.onPrepared();
                }

                //可以转备好自动start(),也可以自己控制start()
//                start();
                Log.i("JuneMediaPlayer", "------setOnPreparedListener.onPrepared() end:status = " + mStatus+"------");
            }
        });
        Log.i("JuneMediaPlayer", "------initPlay() end:status = " + mStatus+"------");
    }

    /**
     * 资源可能为空，或者过大，或其他原因导致无法加载，在这里抓异常
     */
    public void prepare(String path) throws IOException {
        Log.i("JuneMediaPlayer", "------prepare(+"+path+") start:status = " + mStatus+"------");

        //先保证恢复空闲状态
        if (mMediaPlayer != null) {
            reset();
        }

        //设置资源
        if (mStatus == MediaPlayStatus.IDLE) {
            mMediaPlayer.setDataSource(path);
            mStatus = MediaPlayStatus.INITIALIZED;
        }

        //准备
        if (mStatus == MediaPlayStatus.INITIALIZED || mStatus == MediaPlayStatus.STOPPED) {
            mMediaPlayer.prepareAsync();
            mStatus = MediaPlayStatus.PREPARING;
        }
        Log.i("JuneMediaPlayer", "------prepare() end:status = " + mStatus+"------");
    }

    public void prepare(Context context, Uri uri) throws IOException {
        Log.i("JuneMediaPlayer", "------prepare("+uri+") start:status = " + mStatus+"------");
        //先保证恢复空闲状态
        if (mMediaPlayer != null) {
            reset();
        }

        //设置资源
        if (mStatus == MediaPlayStatus.IDLE) {
            mMediaPlayer.setDataSource(context,uri);
            mStatus = MediaPlayStatus.INITIALIZED;
        }

        //准备
        if (mStatus == MediaPlayStatus.INITIALIZED || mStatus == MediaPlayStatus.STOPPED) {
            mMediaPlayer.prepareAsync();
            mStatus = MediaPlayStatus.PREPARING;
        }
        Log.i("JuneMediaPlayer", "------prepare() end:status = " + mStatus+"------");
    }

    /**
     * 暂停播放，调用start()恢复
     */
    public void pause() {
        Log.i("JuneMediaPlayer", "------pause() start:status = " + mStatus+"------");
        if (mStatus == MediaPlayStatus.STARTED || mStatus == MediaPlayStatus.PAUSED) {
            mSingleExecutorService.execute(() -> {
                mMediaPlayer.pause();
                mStatus = MediaPlayStatus.PAUSED;
            });
            //停止刷新进度条
//            stopTimer();
        }
        Log.i("JuneMediaPlayer", "------pause() end:status = " + mStatus+"------");
    }

    /**
     * 播放开始或暂停后停止播放
     * 调用stop()停止播放并导致STARTED,PAUSED,PREPARED,
     * PLAYBACK_COMPLETED状态的MediaPlayer进入STOPPED状态
     * 一旦处于STOPPED钻淘汰，播放不能开始，知道prepare()
     * 或被prepareAsync()调用以将MediaPlayer对象再次设置为PREPARED状态
     */
    public void stop() {
        Log.i("JuneMediaPlayer", "------stop() start:status = " + mStatus+"------");
        if (mStatus == MediaPlayStatus.STARTED || mStatus == MediaPlayStatus.PAUSED ||
                mStatus == MediaPlayStatus.PREPARED || mStatus == MediaPlayStatus.PLAYBACK_COMPLETED ||
                mStatus == MediaPlayStatus.STOPPED) {
            mSingleExecutorService.execute(() -> {
                mMediaPlayer.stop();
                mStatus = MediaPlayStatus.STOPPED;
            });
//            stopTimer();
        }
        Log.i("JuneMediaPlayer", "------stop() end:status = " + mStatus+"------");
    }

    /**
     * 开始或恢复播放，如果之前已暂停播放，将从暂停的位置继续播放
     * 如果播放已停止或从未开始，播放将从头开始
     * isPlaying()可以调用来测试MediaPlayer对象是否处于STARTED状态
     */
    public void start() {
        Log.i("JuneMediaPlayer", "------start() start:status = " + mStatus+"------");
        if (mStatus == MediaPlayStatus.PREPARED || mStatus == MediaPlayStatus.STARTED ||
                mStatus == MediaPlayStatus.PAUSED || mStatus == MediaPlayStatus.PLAYBACK_COMPLETED) {
            mSingleExecutorService.execute(() -> {
                mMediaPlayer.start();
                mStatus = MediaPlayStatus.STARTED;
            });
//            startTimer();
            Log.i("JuneMediaPlayer", "duration = " + mMediaPlayer.getDuration());






        }
        Log.i("JuneMediaPlayer", "------start() end:status = " + mStatus+"------");
    }

    public void seekTo(int position) {
        Log.i("JuneMediaPlayer", "------seekTo() start:status = " + mStatus+"------");
        if (mStatus == MediaPlayStatus.PREPARED || mStatus == MediaPlayStatus.STARTED ||
                mStatus == MediaPlayStatus.PAUSED || mStatus == MediaPlayStatus.PLAYBACK_COMPLETED) {
            mSingleExecutorService.execute(()->{
                mMediaPlayer.seekTo(position);
            });
        }
        Log.i("JuneMediaPlayer", "------seekTo() end:status = " + mStatus+"------");
    }

    /**
     * 将MediaPlayer重置为未初始化的状态。
     * 调用此方法后，您必须通过设置数据源并调用prepare()来再次初始化它
     */
    public void reset(){
        Log.i("JuneMediaPlayer", "------reset() start:status = " + mStatus+"------");
        mMediaPlayer.reset();
        mStatus=MediaPlayStatus.IDLE;
        Log.i("JuneMediaPlayer", "------reset() end:status = " + mStatus+"------");
    }

    /**
     * 开始计时
     */
    public void startTimer(){
        Log.i("JuneMediaPlayer", "------startTimer()------");
        mTimeHandler.postDelayed(timerRun, TIMER_SEEK);
    }

    /**
     * 停止计时
     */
    public void stopTimer(){
        Log.i("JuneMediaPlayer", "------stopTimer()------");
        mTimeHandler.removeCallbacks(timerRun);
    }

    /**
     * 释放与此MediaPlayer相关联的资源。
     * 使用完MediaPlayer后调用此方法被认为是一种很好的做法
     */
    public void release(){
        Log.i("JuneMediaPlayer", "------release() start:status ="+mStatus+"------");
        mSingleExecutorService.execute(()->{
            mMediaPlayer.release();
            mMediaPlayer=null;
            mStatus=MediaPlayStatus.END;
        });
//        stopTimer();
        Log.i("JuneMediaPlayer", "------release() end:status ="+mStatus+"------");
    }

    public void onDestroy(){
        Log.i("JuneMediaPlayer", "------onDestroy() start:status ="+mStatus+"------");
        release();
        if(mUiHandler!=null){
            mUiHandler.removeCallbacksAndMessages(null);
        }
        mOnMediaStateListener=null;
        Log.i("JuneMediaPlayer", "------onDestroy() end:status ="+mStatus+"------");
    }

    public MediaPlayStatus getStatus() {
        return mStatus;
    }

    /**
     * 播放状态监听
     */
    public interface OnMediaStateListener{

        //准备完成
        void onPrepared();

        //当前播放进度
        void onSeekUpdate(int curTimeInt);

        //播放完成
        void onCompletion();

        boolean onError();

    }

    public enum MediaPlayStatus {
        /**
         * 空闲状态
         * 1.使用new创建->IDLE
         * 2.使用reset()->IDLE
         * 这两种方式的区别是：如果测试发生错误（调用getCurrentPosition()等方法
         * 方法1不会回调方法 OnErrorListener.onError()并且对象状态保持不变
         * 方法2会回调方法 OnErrorListener.onError()并且对象状态变为ERROR状态
         */
        IDLE,
        /**
         * 初始化状态
         * setDataSource()->INITIALIZED
         */
        INITIALIZED,
        /**
         * 准备阶段
         * INITIALIZED->prepareAsync()->PREPARING
         * STOPPED->prepareAsync()->PREPARING
         */
        PREPARING,
        /**
         * MediaPlayer对象必须进入Prepared状态，然后才可以播放
         * 1.PREPARING->OnPreparedListener.onPrepare()->PREPARED
         * 2.INITIALIZED->prepare()->PREPARED
         * 3.STOPPED->prepared()->PREPARED
         * 4.PREPARED->seekTo()->PREPARED
         */
        PREPARED,
        /**
         * 1.PREPARED->start()->STARTED
         * 2.PAUSE->start()->STARTED
         * 3.STARTED->seekTo(),start()->STARTED
         * 4.PLAYBACK_COMPLETED&&setLooping(true)->STARTED
         * 5.PLAYBACK+COMPLETED->start()->STARTED
         */
        STARTED,
        /**
         * 1.STARTED->pause()->PAUSED
         * 2.PAUSED->pause(),seekTo()->PAUSED
         */
        PAUSED,
        /**
         * 1.STARTED->stop()=>STOPPED
         * 2.PAUSED->stop()->PAUSE
         * 3.PLAYBACK->stop()->STOPPED
         * 4.STOPPED->stop()->STOPPED
         * 5.PREPARED->stop()->STOPPED
         */
        STOPPED,
        /**
         * 1.STARTED->PLAYBACK_COMPLETED&&setLooping(true)->PLAYBACK_COMPLETED
         * 2.PLAYBACK_COMPLETED->seekTo()->PLAYBACK_COMPLETED
         */
        PLAYBACK_COMPLETED,
        /**
         * onErrorListener.onError()->ERROR
         */
        ERROR,
        /**
         * release()->END
         * 一旦不再使用MediaPlayer对象，release()立即调用
         * 一旦MediaPlayer对象处于End状态，就不能再使用，也不乏回复到其它任何其它状态
         */
        END


    }


}